package com.iot.mqtt.handler;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.iot.common.sms.AliSmsSender;
import com.iot.common.utils.DateUtils;
import com.iot.common.utils.StringUtils;
import com.iot.device.domain.*;
import com.iot.device.service.*;
import com.iot.device.utils.BaiduLocationUtils;
import com.iot.websocket.Topic;
import com.iot.websocket.WebSocketMessageSender;
import com.iot.websocket.message.EventMsgMessage;
import org.eclipse.paho.client.mqttv3.MqttMessage;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Component;

import java.io.UnsupportedEncodingException;
import java.util.Date;

/**
 * 设备消息处理器
 * @author Cao.ning
 * @date 2022/11/11
 */
@Component
public class PressureSensorClientHandler {
    private static final Logger logger = LoggerFactory.getLogger(PressureSensorClientHandler.class);

    @Autowired
    public ThreadPoolTaskExecutor threadPoolTaskExecutor;
    @Autowired
    public IPressureSensorClientService pressureSensorClientService;
    @Autowired
    public IPressureSensorEventService pressureSensorEventService;
    @Autowired
    public IPressureSensorParamService pressureSensorParamService;
    @Autowired
    public AliSmsSender aliSmsSender;

    // 终端发送主题：/edge/single/${pKey}/${sn}/info
    public static final String TOPIC_EDGE_INFO = "info";// 设备上报设备信息 启动
    public static final String TOPIC_EDGE_RTG = "rtg";// 设备上报实时数据 周期/按需
    public static final String TOPIC_EDGE_CALL = "call";// 设备实时数据召读返回 按需
    public static final String TOPIC_EDGE_SET = "set";// 设备指令响应 按需
    public static final String TOPIC_EDGE_CHANGE = "change";// 设备参数配置更改上报 按需
    // 终端订阅主题：/cloud/single/${pKey}/${sn}/info
    public static final String TOPIC_CLOUD_INFO = "info";// 设备信息应答 按需
    public static final String TOPIC_CLOUD_RTG = "rtg";// 系统召读实时数据应答 按需
    public static final String TOPIC_CLOUD_CALL = "call";// 系统召读设备实时数据 按需
    public static final String TOPIC_CLOUD_SET = "set";// 系统下发设备指令 按需
    public static final String TOPIC_CLOUD_CHANGE = "change";// 系统对设备参数配置更改应答 按需

    /**
     * 处理消息
     *
     * @param topic
     * @param message
     */
    public void handleMessage(String topic, MqttMessage message) {
        // 必须用线程池处理，mqtt消息是单线程，处理完一个后才处理下一个，避免消息多了处理不了多余消息
        Date now = DateUtils.getNowDate();
        threadPoolTaskExecutor.execute(new Runnable() {
            @Override
            public void run() {
                logger.info("收到压力传感器监测设备消息：{}， {}", topic, message);
                try {
                    if (message == null) {
                        return;
                    }
                    String[] topicSplit = topic.split("\\/");
                    if (topicSplit.length < 5) {
                        logger.info("不符合规则的主题：{}", topic);
                        return;
                    }
                    String pKey = topicSplit[2];
                    String sn = topicSplit[3];
                    if (StringUtils.isEmpty(sn)) {
                        return;
                    }
                    String msgContent = new String(message.getPayload(), "UTF-8");
                    JSONObject msgJson = JSON.parseObject(msgContent);

                    PressureSensorClient pressureSensorClient = handleClientData(msgJson, now, pKey, sn);

                    JSONObject payload = msgJson.getJSONObject("payload");
                    if (payload != null) {
                        Integer alarm = payload.getInteger("alarm");

                        // TODO 数据修正
                        Double limitAlarmHh = payload.getDouble("hHLimitAlarm");
                        Double limitAlarmH  = payload.getDouble("hLimitAlarm");
                        Double limitAlarmL  = payload.getDouble("lLimitAlarm");
                        Double limitAlarmLl = payload.getDouble("lLLimitAlarm");
                        Double pressValue = payload.getDouble("pressValue");
                        if(limitAlarmL < pressValue && pressValue < limitAlarmH){
                            alarm = 0;
                        }else if(pressValue < limitAlarmLl){
                            alarm = 1;
                        }else if(limitAlarmLl < pressValue && pressValue < limitAlarmL){
                            alarm = 2;
                        }else if(limitAlarmH < pressValue && pressValue < limitAlarmHh){
                            alarm = 3;
                        }else if(limitAlarmHh < pressValue){
                            alarm = 4;
                        }


                        // 1.设备上报实时数据与反馈主题
                        if (TOPIC_EDGE_RTG.equals(topicSplit[4])) {
                            /*
                        {
                            "devtype": "PGL",
                            "sysId": "smkj",
                            "seq": "rtg1688452626000",
                            "ack": "0",
                            "parameter": {
                                "devtype": "PGL",
                                "sysId": "smkj",
                                "sVer": "1.0.0",
                                "hVer": "1.0.0",
                                "meId": "00000000000000000000",
                                "connType": "G",
                                "power": "0",
                                "model": "0"
                            },
                            "payload": {
                                "PressValue": "0",
                                "alarm": "1",
                                "solenoidValveOnOff": "0",
                                "solenoidValveOnState": "0",
                                "HHLimitAlarm": "250",
                                "HLimitAlarm": "245",
                                "LLLimitAlarm": "0",
                                "LLimitAlarm": "5",
                                "Dc": "0",
                                "Longitude": "118.091401",
                                "Latitude": "39.582459"
                            },
                            "ts": "1688452626000"
                        }
                        */
                            PressureSensorEvent event = new PressureSensorEvent();
                            event.setSn(sn);
                            event.setClient(pressureSensorClient);
                            event.setEventDate(now);
                            event.setDeptId(pressureSensorClient.getDeptId());
                            event.setSendTime(new Date(msgJson.getLong("ts")));
                            event.setReceiveTime(now);
                            event.setPressValue(payload.getDouble("PressValue"));
                            event.setSolenoidValveOnState(payload.getInteger("solenoidValveOnState"));
                            event.setAlarm(alarm);
                            event.setMsgContent(payload.toJSONString());
                            pressureSensorEventService.insertPressureSensorEvent(event);

                            if(alarm != null && alarm > 0){
                                // alarm 是 1/2/3/4 属于报警
//                                String PhoneNumbers = null;
//                                String SignName = null;
//                                String TemplateCode = null;
//                                String TemplateParam = null;
//                                aliSmsSender.send(PhoneNumbers, SignName, TemplateCode, TemplateParam, null, null);
                                WebSocketMessageSender.send(EventMsgMessage.getInstance(Topic.PS_EVENT_MSG, event.getDeptId(), JSON.parseObject(JSON.toJSONString(event))));
                            }
                        }

                        handleClientParam(payload, sn, topic, now);
                    }
                } catch (UnsupportedEncodingException e) {
                    e.printStackTrace();
                }
            }
        });
    }

    /**
     * 设备数据处理
     * @param msgJson
     * @param now
     * @param pKey
     * @param sn
     * @return
     */
    private PressureSensorClient handleClientData(JSONObject msgJson, Date now, String pKey, String sn) {
        PressureSensorClient pressureSensorClient = pressureSensorClientService.selectPressureSensorClientBySn(sn);
        if (pressureSensorClient == null)
        {
            // 如果是新注册的设备
            pressureSensorClient = new PressureSensorClient();
            pressureSensorClient.setCreateTime(now);
            pressureSensorClient.setRemark("设备自动注册");
            pressureSensorClient.setCreateBy("AutoRegister");
            pressureSensorClient.setUserId(1L);
            pressureSensorClient.setDeptId(200L);
        }
        pressureSensorClient.setUpdateTime(now);
        pressureSensorClient.setSn(sn);
        pressureSensorClient.setDeviceName(sn);
        pressureSensorClient.setPkey(pKey);

        JSONObject parameter = msgJson.getJSONObject("parameter");
        if(parameter != null)
        {
            pressureSensorClient.setDevtype(msgJson.getString("devtype"));
            pressureSensorClient.setSysId(msgJson.getString("sysId"));
            pressureSensorClient.setSver(parameter.getString("sVer"));
            pressureSensorClient.setHver(parameter.getString("hVer"));
            pressureSensorClient.setMeid(parameter.getString("meId"));
            pressureSensorClient.setConnType(parameter.getString("connType"));
            pressureSensorClient.setDc(parameter.getLong("dc"));
            pressureSensorClient.setPower(parameter.getInteger("power"));
            pressureSensorClient.setSignalStrength(msgJson.getString("rssi"));
            pressureSensorClient.setLowAlarm(msgJson.getBoolean("lowAlarmOrNot"));
            pressureSensorClient.setFactoryId(msgJson.getString("factoryId"));
            pressureSensorClient.setUpdateTime(now);

            Double longitude = parameter.getDouble("longitude");
            Double latitude = parameter.getDouble("latitude");
            if(longitude != null && latitude != null){
                // 如果经纬度变化了，重新定位
                if(!longitude.equals(pressureSensorClient.getLongitude()) || !latitude.equals(pressureSensorClient.getLatitude())){
                    pressureSensorClient.setLongitude(parameter.getDouble("longitude"));
                    pressureSensorClient.setLatitude(parameter.getDouble("latitude"));
                    pressureSensorClient.setAddress(BaiduLocationUtils.getLocation(parameter.getDouble("longitude"), parameter.getDouble("latitude")));
                }
            }
        }
                   /* if (TOPIC_EDGE_INFO.equals(topicSplit[4]) || TOPIC_EDGE_CALL.equals(topicSplit[4]))
                    {
                            *//*{
                                "devtype": "ch4_alarmer",
                                "sysId": "ecej",
                                "seq": "A3880",
                                "ack": "1",
                                "parameter": {
                                    "sVer": "1.0.1",
                                    "hVer": "1.0.0",
                                    "meId ": "89860419151871872499",
                                    "connType": "G",
                                    "power": "0",
                                    "Dc": "3600",
                                    "ct": "1661843863006",
                                    "Longitude ": "0.0",
                                    "Latitude ": "0.0"
                                },
                                "ts": "1661843863006"
                            }*//*
                        pressureSensorClient.setDevtype(msgJson.getString("devtype"));
                        pressureSensorClient.setSysId(msgJson.getString("sysId"));
                        pressureSensorClient.setSver(parameter.getString("sVer"));
                        pressureSensorClient.setHver(parameter.getString("hVer"));
                        pressureSensorClient.setMeid(parameter.getString("meId"));
                        pressureSensorClient.setConnType(parameter.getString("connType"));
                        pressureSensorClient.setPower(parameter.getInteger("power"));
                        pressureSensorClient.setDc(parameter.getLong("dc"));
                        pressureSensorClient.setCt(parameter.getLong("ct"));
                        pressureSensorClient.setLongitude(parameter.getDouble("Longitude"));
                        pressureSensorClient.setLatitude(parameter.getDouble("Latitude"));
                        pressureSensorClient.setAddress(BaiduLocationUtils.getLocation(parameter.getDouble("Longitude"), parameter.getDouble("Latitude")));
                    }*/
        if(pressureSensorClient.getId() == null){
            pressureSensorClientService.insertPressureSensorClient(pressureSensorClient);
        }else{
            pressureSensorClientService.updatePressureSensorClient(pressureSensorClient);
        }
        return pressureSensorClient;
    }

    private void handleClientParam(JSONObject payload, String sn, String topic, Date now) {
        Double limitAlarmHh = payload.getDouble("hHLimitAlarm");
        Double limitAlarmH  = payload.getDouble("hLimitAlarm");
        Double limitAlarmL  = payload.getDouble("lLimitAlarm");
        Double limitAlarmLl = payload.getDouble("lLLimitAlarm");
        Double rangeH = payload.getDouble("rangeH");
        Double rangeL = payload.getDouble("rangeL");
        if(limitAlarmHh != null || limitAlarmH != null || limitAlarmL != null || limitAlarmLl != null)
        {
            PressureSensorParam pressureSensorParam = pressureSensorParamService.pressureSensorParamBySn(sn);
            if(pressureSensorParam == null){
                pressureSensorParam = new PressureSensorParam();
            }
            pressureSensorParam.setSn(sn);
            pressureSensorParam.setLimitAlarmHh(limitAlarmHh);
            pressureSensorParam.setLimitAlarmH(limitAlarmH);
            pressureSensorParam.setLimitAlarmL(limitAlarmL);
            pressureSensorParam.setLimitAlarmLl(limitAlarmLl);
            pressureSensorParam.setRangeH(rangeH == null ? 0 : rangeH);
            pressureSensorParam.setRangeL(rangeL == null ? 0 : rangeL);
            pressureSensorParam.setUpdateTime(now);
            if(pressureSensorParam.getId() == null)
            {
                pressureSensorParamService.insertPressureSensorParam(pressureSensorParam);
            }
            else
            {
                pressureSensorParamService.updatePressureSensorParam(pressureSensorParam);
            }
        }
    }
}